<?php


namespace RedMVC\Controller;
use RedMVC;

/**
 * Front class
 *
 * @category    RedMVC
 * @package     Controller
 * @author      Jan Fischer, bitWorking <info@bitworking.de>
 */
class Front{

    public static $request;
    public static $response;
    protected static $_errors = array();

    public static function addError($error){
        self::$_errors[] = $error;
    }
    
    public static function init(){
        self::$request = new RedMVC\Http\Request();
        RedMVC\Registry::set('RedMVC_Request', self::$request);
        
        self::$response = new RedMVC\Http\Response();
        RedMVC\Registry::set('RedMVC_Response', self::$response);
    }

    public static function run(){
        RedMVC\Event\Dispatcher::fire(RedMVC\Event\Dispatcher::EVENT_DISPATCH_PRE);

        self::runControllerAction(
            self::$request->getControllerName(),
            self::$request->getActionName()
        );        
    }

    public static function runControllerAction($controllerName, $actionName){
        $controllerName     = self::_getControllerActionName($controllerName);
        $controllerClass    = ucfirst($controllerName).'Controller';
        $actionName         = self::_getControllerActionName($actionName);
        $actionMethod       = $actionName.'Action';

        $controllerPath     = APP_PATH.DS.'controllers'.DS.$controllerClass.'.php';

        if(file_exists($controllerPath)){
            $controllerClass    = "controllers\\".$controllerClass;
            $controller         = new $controllerClass();
            $controller->init();
            if(method_exists($controller, $actionMethod)){
                // load view                
                $viewScript         = APP_PATH.DS.'views'.DS.'scripts'.DS.$controllerName.DS.$actionName.'.phtml';
                $loc                = RedMVC\Registry::get('RedMVC_Locale');
                $viewScriptLocale   = APP_PATH.DS.'views'.DS.'scripts'.DS.$controllerName.DS.$actionName.'_'.$loc.'.phtml';
                $view               = null;
                if(file_exists($viewScript)){
                    $view = new RedMVC\View($viewScript);
                }
                else if(file_exists($viewScriptLocale)){
                    $view = new RedMVC\View($viewScriptLocale);                    
                }

                $config = RedMVC\Registry::get('RedMVC_Config');
                $db     = RedMVC\Registry::get('RedMVC_Db');

                // set viewHelper
                $viewHelper = new RedMVC\ViewHelper();
                $viewHelper->setRequest(self::$request);
                $viewHelper->setDb($db);
                $viewHelper->setView($view);
                $viewHelper->setController($controller);
                RedMVC\Registry::set('RedMVC_ViewHelper', $viewHelper);

                // set request, response, view
                $controller->setRequest(self::$request);
                $controller->setResponse(self::$response);
                $controller->setView($view);

                // load layout
                $layoutScript = $config->defaultLayout;
                $controller->loadLayout($layoutScript);

                // set db
                $controller->setDb($db);

                // run action
                $controller->$actionMethod();

                // output
                if($controller->getLayoutEnabled()){
                    $layout = $controller->getLayout();
                    $layout->mergeErrors(self::$_errors);
                    if($controller->getViewEnabled()){                        
                        if(null === $controller->getView()){
                            throw new \Exception('View '.$viewScript.' doesn\'t exist.');
                        }                        
                        $layout->setContent($controller->getView()->render());
                    }
                    //echo $layout->render();
                    self::$response->write($layout->render());
                    self::$response->flush();
                }
                else if($controller->getViewEnabled()){
                    if(null === $controller->getView()){
                        throw new \Exception('View '.$viewScript.' doesn\'t exist.');
                    }
                    //echo $controller->getView()->render();
                    self::$response->write($controller->getView()->render());
                    self::$response->flush();
                }
            }
            else{
                $return = RedMVC\Event\Dispatcher::fire(RedMVC\Event\Dispatcher::EVENT_ACTION_NOT_EXISTS);
                if(null === $return){
                    throw new \Exception('Action '.$actionName.' doesn\'t exist.', 404);
                }
            }
        }
        else{
            $return = RedMVC\Event\Dispatcher::fire(RedMVC\Event\Dispatcher::EVENT_CONTROLLER_NOT_EXISTS);
            if(null === $return){
                throw new \Exception('Controller '.$controllerName.' doesn\'t exist.', 404);
            }
        }

        // postDispatch
        self::$request->setReferrer();

        RedMVC\Event\Dispatcher::fire(RedMVC\Event\Dispatcher::EVENT_DISPATCH_POST);
    }

    private static function _getControllerActionName($name){
        $name = strtolower($name);
        $name = str_replace('-', ' ', $name);
        $name = ucwords($name);
        $name = str_replace(' ', '', $name);
        $name = lcfirst($name);
        return $name;
    }

    // url helper

    public static function redirect($controller, $action, $params = array(), $absoluteUrl = false){
        self::redirectUrl(self::url($controller, $action, $params, $absoluteUrl));
    }

    public static function redirectUrl($url){
        header("Location: ".$url);
        exit;
    }

    public static function url($controller, $action, $params = array(), $absoluteUrl = false){
        if(!$absoluteUrl){
          return self::$request->getBaseUrl().self::buildUrl($controller, $action, $params);
        }
        return self::$request->getRootUrl().self::buildUrl($controller, $action, $params);
    }

    public static function selfUrl($paramsToExclude = null, $params = array(), $absoluteUrl = false){
        $_params = array();
        if(null === $paramsToExclude){
            $_params = self::$request->getParams();
        }
        else if(is_array($paramsToExclude)){
            foreach(self::$request->getParams() as $variable => $value){
                if(!in_array($variable, $paramsToExclude)){
                    if(is_array($value)){
                        // TODO: value is array
                    }
                    else{
                        $_params[$variable] = $value;
                    }
                }
    		}
        }
        $_params = array_merge($_params, $params);
        return self::url(
            self::$request->getControllerName(),
            self::$request->getActionName(),
            $_params,
            $absoluteUrl
        );
    }

    public static function buildUrl($controller, $action, $params = array()){
        $router = RedMVC\Registry::get('RedMVC_Router');
        return $router->buildUrl($controller, $action, $params);
    }
}